package com.zboot.zbootadmin.project.system.role.service.imp;


import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.zboot.zbootadmin.common.security.service.TokenService;
import com.zboot.zbootadmin.common.utils.DateUtils;
import com.zboot.zbootadmin.common.utils.ServletUtils;
import com.zboot.zbootadmin.common.utils.StringUtils;
import com.zboot.zbootadmin.project.system.menu.entity.SysMenu;
import com.zboot.zbootadmin.project.system.menu.entity.SysRoleMenu;
import com.zboot.zbootadmin.project.system.menu.service.SysMenuService;
import com.zboot.zbootadmin.project.system.menu.service.SysRoleMenuService;
import com.zboot.zbootadmin.project.system.role.entity.SysRole;
import com.zboot.zbootadmin.project.system.role.entity.dto.RoleDto;
import com.zboot.zbootadmin.project.system.role.mapper.SysRoleMapper;
import com.zboot.zbootadmin.project.system.role.service.SysRoleService;
import com.zboot.zbootadmin.project.system.user.domain.SysUser;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色信息表 服务实现类
 * </p>
 *
 * @author zyt
 * @since 2020-07-18
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Autowired
    private SysRoleMenuService roleMenuService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysMenuService menuService;

    /**
     *
     * @Description: 
     * 
     * @author: zyt
     * @date: 20:35 2020/9/9 
     * @param: [roleDto]
     * @return: com.alibaba.fastjson.JSONObject
     *
     */
    @Override
    public JSONObject queryRoleList(RoleDto roleDto) {
        QueryWrapper queryWrapper = new QueryWrapper();
        if (roleDto != null) {
            if (StringUtils.isNotBlank(roleDto.getRoleName())) {
                queryWrapper.like("role_name",roleDto.getRoleName());
            }
            if (StringUtils.isNotBlank(roleDto.getStatus())) {
                queryWrapper.like("status",roleDto.getStatus());
            }
            if (StringUtils.isNotBlank(roleDto.getCreateTime())) {
                queryWrapper.like("create_time",roleDto.getCreateTime());
            }

        }
        if(tokenService.getLoginUser(ServletUtils.getRequest()).getUser().getIsAdmin()!=0) {
            queryWrapper.eq("create_by",tokenService.getLoginUser(ServletUtils.getRequest()).getUser().getUserName());
        }
        if (roleDto.getPageNum()!=0&&roleDto.getPageSize()!=0) {
            PageHelper.startPage(roleDto.getPageNum(),roleDto.getPageSize());
        }
        List<SysRole> result = this.list(queryWrapper);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("result",result);
        jsonObject.put("total",this.count(queryWrapper));
        return jsonObject;
    }

    @Override
    @Transactional
    public void insertRole(SysRole sysRole) {
        SysRole role = new SysRole();
        BeanUtils.copyProperties(sysRole,role);
        role.setStatus("0");
        role.setDelFlag("0");
        role.setCreateBy(tokenService.getLoginUser(ServletUtils.getRequest()).getUser().getUserName());
        role.setCreateTime(DateUtils.getTime());
        role.setUpdateBy(tokenService.getLoginUser(ServletUtils.getRequest()).getUser().getUserName());
        role.setUpdateTime(new Date());
        saveOrUpdate(role);
        Collection<SysRoleMenu> sysRoleMenus = new ArrayList<>();
        if ( sysRole.getMenuIds().size()!=0) {
            sysRole.getMenuIds().stream().forEach(obj->{
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(role.getRoleId());
                sysRoleMenu.setMenuId(Long.valueOf(obj));
                sysRoleMenus.add(sysRoleMenu);
            });
        }
        roleMenuService.saveBatch(sysRoleMenus);
    }

    @Override
    @Transactional
    public void deleteRole(String[] roleIds) {

        Arrays.asList(roleIds).stream().forEach(roleId->{
            Map<String,Object> map = new HashMap<>();
            map.put("role_id",roleId);
            roleMenuService.removeByMap(map);
        });
        removeByIds(Arrays.asList(roleIds));
    }

    @Override
    @Transactional
    public JSONObject queryRoleById(String roleId) {
        JSONObject result = new JSONObject();
        SysRole sysRole = getById(roleId);
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("role_id",roleId);
        List<SysRoleMenu> sysRoleMenus = roleMenuService.list(queryWrapper);
        result.put("sysRole",sysRole);
        result.put("sysRoleMenus",sysRoleMenus);
        return result;
    }

    @Override
    @Transactional
    public void editRole(SysRole sysRole) {

        Collection<SysRoleMenu> sysRoleMenus = new ArrayList<>();
        if (sysRole.getMenuIds()!=null ) {
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("role_id",sysRole.getRoleId());
            roleMenuService.remove(queryWrapper);
            List<String> menuIds = new ArrayList<>();
            List<SysRoleMenu> sysRoleMenuList = roleMenuService.list(queryWrapper);
            sysRoleMenuList.stream().forEach(roleMenu->{
                menuIds.add(roleMenu.getMenuId().toString());
            });
            if (menuIds.size()!=0) {
                List<SysMenu> menus = menuService.listByIds(menuIds).stream().filter(menu->"B".equals(menu.getMenuType())).collect(Collectors.toList());
                List<SysMenu> parentBMenus = null;
                if (menus!=null) {
                    for (SysMenu menu:menus) {
                        QueryWrapper wrapper = new QueryWrapper();
                        wrapper.eq("menu_id",menu.getParentId());
                        parentBMenus = menuService.list(wrapper);
                        List<String> removedMenuIds = new ArrayList<>();
                        parentBMenus.stream().forEach(menuObj->removedMenuIds.add(menuObj.getMenuId().toString()));
                        List<String> finalIds = menuIds.stream().filter(id->!removedMenuIds.contains(id)).collect(Collectors.toList());
                        queryWrapper.in("menu_id",finalIds);
                    }
                }
            }


            sysRole.getMenuIds().stream().forEach(obj->{
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(sysRole.getRoleId());
                sysRoleMenu.setMenuId(Long.valueOf(obj));
                sysRoleMenus.add(sysRoleMenu);
            });
        }
        roleMenuService.saveBatch(sysRoleMenus);
        updateById(sysRole);
    }

    @Override
    public Set<String> selectRolePermissionByUserId(Long userId) {
        List<SysRole> perms = roleMapper.selectRolePermissionByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (SysRole perm : perms)
        {
            if (StringUtils.isNotNull(perm))
            {
                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
            }
        }
        return permsSet;
    }
}
